package com.hulman.oms.service;

import com.hulman.oms.bean.*;
import com.hulman.oms.bean.Workbench;
import com.hulman.oms.dao.MenuDao;
import com.hulman.oms.dao.WorkbenchDao;
import com.hulman.oms.dao.UserDao;
import com.hulman.oms.exception.IoTException;
import com.hulman.oms.util.CipherUtil;
import com.hulman.oms.util.CodeGenerator;
import com.hulman.oms.util.NumberUtil;
import com.hulman.oms.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.map.HashedMap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.*;

/**
 * @Author: maxwellens
 */
@Service
@Slf4j
public class UserService
{
    @Autowired
    private UserDao userDao;
    @Autowired
    private RoleService roleService;
    @Autowired
    private MenuDao menuDao;
    @Autowired
    private WorkbenchDao workbenchDao;
    @Autowired
    private MsgService msgService;
    @Autowired
    private LeaderShiftService leaderShiftService;

    public List<User> findAllUsers()
    {
        Map<String, Object> map = new HashMap<>();
        return userDao.findUsers(map);
    }

    public Integer findAllUsersCount()
    {
        Map<String, Object> map = new HashMap<>();
        return userDao.findUsersCount(map);
    }

    public List<User> findUsers(Map<String, Object> map)
    {
        List<User> users = userDao.findUsers(map);
        for (User user : users)
        {
            String roles = user.getRoles();
            if (!StringUtils.isEmpty(roles))
            {
                String roleNames = roleService.findRoleNamesByIds(roles);
                user.setRoleNames(roleNames);
            }
        }
        return users;
    }

    public List<User> findUsersByRoleId(Integer roleId)
    {
        Map<String, Object> map = new HashMap<>();
        map.put("roleId", roleId);
        List<User> users = userDao.findUsers(map);
        for (User user : users)
        {
            String roles = user.getRoles();
            if (!StringUtils.isEmpty(roles))
            {
                String roleNames = roleService.findRoleNamesByIds(roles);
                user.setRoleNames(roleNames);
            }
        }
        return users;
    }

    public List<User> findUsersByRoleIds(String roleIds)
    {
        if (StringUtil.isEmpty(roleIds))
        {
            return Collections.emptyList();
        } else
        {
            Map<Integer, User> map = new HashedMap();
            int[] ids = NumberUtil.parseIntArray(roleIds);
            for (int id : ids)
            {
                List<User> list = findUsersByRoleId(id);
                for (User user : list)
                {
                    map.put(user.getId(), user);
                }
            }
            List<User> result = new ArrayList<>();
            for (User user : map.values())
            {
                result.add(user);
            }
            return result;
        }
    }

    public User findFirstUserByRoleId(Integer roleId)
    {
        Map<String, Object> map = new HashMap<>();
        map.put("roleId", roleId);
        List<User> users = userDao.findUsers(map);
        if (users.size() == 0)
        {
            return null;
        } else
        {
            User user = users.get(0);
            String roles = user.getRoles();
            if (!StringUtils.isEmpty(roles))
            {
                String roleNames = roleService.findRoleNamesByIds(roles);
                user.setRoleNames(roleNames);
            }
            return user;
        }
    }

    public Integer findUsersCount(Map<String, Object> map)
    {
        return userDao.findUsersCount(map);
    }

    public Result findUsersResult(Map<String, Object> map)
    {
        Integer page = (Integer) map.get("page");
        Integer limit = (Integer) map.get("limit");
        if (page != null && limit != null)
        {
            map.put("start", (page - 1) * limit);
            map.put("length", limit);
        }
        int count = userDao.findUsersCount(map);
        List<User> data = findUsers(map);
        return new Result(data, count);
    }

    public User findUserById(Integer id)
    {
        User user = userDao.findUserById(id);
        if (user != null)
        {
            return setUserRoles(user);
        } else
        {
            return null;
        }
    }

    public User findUserByName(String name)
    {
        User user = userDao.findUserByName(name);
        if (user != null)
        {
            return setUserRoles(user);
        } else
        {
            return null;
        }
    }

    public User findUserByAccount(String account)
    {
        User user = userDao.findUserByAccount(account);
        if (user != null)
        {
            return setUserRoles(user);
        } else
        {
            return null;
        }
    }

    public User findUserByMobile(String name)
    {
        User user = userDao.findUserByMobile(name);
        if (user != null)
        {
            return setUserRoles(user);
        } else
        {
            return null;
        }
    }

    public User findUserByLoginName(String loginName)
    {
        User user = userDao.findUserByLoginName(loginName);
        if (user != null)
        {
            return setUserRoles(user);
        } else
        {
            return null;
        }
    }

    public User findUserByIdOrName(Integer id, String name)
    {
        User user = null;
        if (id != null)
        {
            user = userDao.findUserById(id);
        } else if (!StringUtils.isEmpty(name))
        {
            user = userDao.findUserByName(name);
        }
        if (user != null)
        {
            return setUserRoles(user);
        } else
        {
            return null;
        }
    }

    private User setUserRoles(User user)
    {
        String roles = user.getRoles();
        if (!StringUtils.isEmpty(roles))
        {
            String roleNames = roleService.findRoleNamesByIds(roles);
            user.setRoleNames(roleNames);
        }
        return user;
    }


    //@Transactional(rollbackFor = Exception.class)
    public void saveUser(User user)
    {
        if (user.getId() != null && user.getId() != 0)
        {
            userDao.updateUser(user);
        } else
        {
            /*if (userDao.findUserByName(user.getName()) != null)
            {
                throw new IoTException("姓名" + user.getName() + "已存在");
            }*/
            if (userDao.findUserByAccount(user.getAccount()) != null)
            {
                throw new IoTException("账号" + user.getAccount() + "已存在");
            }
            if (userDao.findUserByMobile(user.getMobile()) != null)
            {
                throw new IoTException("手机号" + user.getMobile() + "已存在");
            }
            user.setCode(CodeGenerator.nextCode());
            user.setPassword(CipherUtil.encrypt(user.getAccount(), User.DEFAULT_PASSWORD));
            user.setIsEnabled(User.STATE_ENABLED);
            if (!StringUtils.isEmpty(user.getRoleNames()))
            {
                user.setRoles(roleService.findRoleIdsByNames(user.getRoleNames()));
            }
            if (user.getSignState() == null)
            {
                user.setSignState(User.SIGN_STATE_OFF);
            }
            if (user.getSync() == null)
            {
                user.setSync(0);
            }
            userDao.insertUser(user);
        }
    }

    //@Transactional(rollbackFor = Exception.class)
    public void deleteUserById(Integer id)
    {
        User user = userDao.findUserById(id);
        if (user != null)
        {
            userDao.deleteUserById(id);
        }
    }

    /**
     * 用户ids转企业微信accounts
     *
     * @param userIds   用户ids
     * @param delimiter 分隔符
     * @return
     */
    public String convertToAccounts(String userIds, String delimiter)
    {
        if (StringUtil.isEmpty(userIds))
        {
            return "";
        }
        StringBuilder sb = new StringBuilder();
        String[] ids = userIds.split(",");
        for (int i = 0; i < ids.length; i++)
        {
            Integer userId = Integer.parseInt(ids[i]);
            User user = userDao.findUserById(userId);
            if (user != null)
            {
                if (i == ids.length - 1)
                {
                    sb.append(user.getAccount());
                } else
                {
                    sb.append(user.getAccount()).append(delimiter);
                }
            }
        }
        return sb.toString();
    }

    public String convertToAccount(Integer userId)
    {
        User user = userDao.findUserById(userId);
        if (user != null)
        {
            return user.getAccount();
        } else
        {
            return "";
        }
    }

    /**
     * 用户清单转企业微信accounts
     *
     * @param users
     * @param delimiter
     * @return
     */
    public String convertToAccounts(List<User> users, String delimiter)
    {
        if (users.size() == 0)
        {
            return "";
        }
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < users.size(); i++)
        {
            User user = users.get(i);
            if (i == users.size() - 1)
            {
                sb.append(user.getAccount());
            } else
            {
                sb.append(user.getAccount()).append(delimiter);
            }
        }
        return sb.toString();
    }

    public void deleteUsers(String ids)
    {
        userDao.deleteUsers(ids);
    }

    public void toggleState(Integer id)
    {
        userDao.toggleState(id);
    }

    public void resetPassword(Integer id)
    {
        User user = userDao.findUserById(id);
        String password = CipherUtil.encrypt(user.getAccount(), User.DEFAULT_PASSWORD);
        userDao.changePassword(id, password);
    }

    public void changePassword(Integer id, String newPassword)
    {
        User user = userDao.findUserById(id);
        String encryptedPassword = CipherUtil.encrypt(user.getAccount(), newPassword);
        userDao.changePassword(id, encryptedPassword);
    }

    public void changeSync(Integer id, Integer sync)
    {
        userDao.changeSync(id, sync);
    }

    public List<Integer> findOwnedMenus(Integer userId)
    {
        Set<Integer> result = new HashSet<>();
        User user = userDao.findUserById(userId);
        if (user == null)
        {
            return new ArrayList<>();
        }
        String roles = user.getRoles();
        String[] roleIds = roles.split(",");
        for (String item : roleIds)
        {
            Integer roleId = Integer.valueOf(item);
            Role role = roleService.findRoleById(roleId);
            String menus = role.getMenus();
            if (menus != null)
            {
                String[] menuIds = menus.split(",");
                for (String m : menuIds)
                {
                    Integer menuId = Integer.valueOf(m);
                    result.add(menuId);
                    Menu menu = menuDao.findMenuById(menuId);
                    if (menu != null)
                    {
                        result.add(menu.getParentId());
                    }
                }
            }
        }
        return new ArrayList<>(result);
    }

    public List<Integer> findOwnedWorkbenches(Integer userId)
    {
        Set<Integer> result = new HashSet<>();
        User user = userDao.findUserById(userId);
        if (user == null)
        {
            return new ArrayList<>();
        }
        String roles = user.getRoles();
        String[] roleIds = roles.split(",");
        for (String item : roleIds)
        {
            Integer roleId = Integer.valueOf(item);
            Role role = roleService.findRoleById(roleId);
            String works = role.getWorkbenches();
            if (!StringUtils.isEmpty(works))
            {
                String[] workbenchIds = works.split(",");
                for (String m : workbenchIds)
                {
                    Integer workbenchId = Integer.valueOf(m);
                    result.add(workbenchId);
                    Workbench module = workbenchDao.findWorkbenchById(workbenchId);
                    if (module != null)
                    {
                        result.add(module.getParentId());
                    }
                }
            }
        }
        return new ArrayList<>(result);
    }

    /**
     * 成为值班长
     *
     * @param id
     */
    @Transactional(rollbackFor = Exception.class)
    public void takeShiftLeader(Integer id)
    {
        User preShiftLeader = userDao.findShiftLeader();
        userDao.untakeShiftLeaderForAll();
        userDao.takeShiftLeader(id);
        User curShiftLeader = userDao.findShiftLeader();
        LeaderShift shift = new LeaderShift();
        //通知交接人
        if (preShiftLeader != null)
        {
            shift.setLeaderId1(preShiftLeader.getId());
            shift.setLeaderName1(preShiftLeader.getName());

            Msg msg = new Msg();
            msg.setOwnerId(preShiftLeader.getId());
            msg.setOwnerName(preShiftLeader.getName());
            msg.setType(Msg.TYPE_SYS);
            msg.setTitle("系统提醒");
            msg.addItem("系统提醒", curShiftLeader.getName() + "已成为当班值班长");
            msgService.sendMsg(msg);
        }
        //交接记录
        shift.setLeaderId2(curShiftLeader.getId());
        shift.setLeaderName2(curShiftLeader.getName());
        shift.setShiftTime(new Date());
        leaderShiftService.saveLeaderShift(shift);
    }

    /**
     * 获取当前值班长
     *
     * @return
     */
    public User findShiftLeader()
    {
        return userDao.findShiftLeader();
    }

    /**
     * 项目经理
     *
     * @return
     */
    public User findProjectManager()
    {
        return findFirstUserByRoleId(1);
    }

    /**
     * 常务经理
     *
     * @return
     */
    public User findStandingManager()
    {
        return findFirstUserByRoleId(2);
    }

    /**
     * 根据区域匹配巡检负责人
     * 规则：在所有角色是巡检负责人当中匹配区域，匹配不到的默认返回第一个
     *
     * @return
     */
    public User findPatrolDirector(String area)
    {
        List<User> users = findUsersByRoleId(3);
        for (User user : users)
        {
            if (!StringUtil.isEmpty(area) && area.equals(user.getArea()))
            {
                return user;
            }
        }
        if (users.size() > 0)
        {
            return users.get(0);
        } else
        {
            return null;
        }
    }

    /**
     * 维修负责人
     *
     * @return
     */
    public User findRepairDirector()
    {
        return findFirstUserByRoleId(4);
    }

    public List<UserStat> statUsers()
    {
        List<UserStat> list = userDao.statUsers();
        for (UserStat userStat : list)
        {
            userStat.setRoles(roleService.findRoleNamesByIds(userStat.getRoles()));
            if (userStat.getSignState() == 1)
            {
                userStat.setOnDuty("在岗");
            } else if (userStat.getSignState() == 0)
            {
                userStat.setOnDuty("离岗");
            } else
            {
                userStat.setOnDuty("未知");
            }
        }
        return list;
    }

    public Integer findOnDutyUsersCount()
    {
        return userDao.findOnDutyUsersCount();
    }

    /**
     * 人员工作量统计
     *
     * @return
     */
    public List<Map<String, Object>> statUserWorkload(Integer limit)
    {
        return userDao.statUserWorkload(limit);
    }

    public List<NameValue> statDailyWorkOrders(Integer days)
    {
        return userDao.statDailyWorkOrders(days);
    }

}
